package game.module.mj.processor;

import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import game.common.PlayingRoleMsgProcessor;
import game.entity.PlayingRole;
import game.module.mj.MjConstants;
import game.module.mj.bean.CChiHuRight;
import game.module.mj.bean.MjRound;
import game.module.mj.bean.TagAnalyseItem;
import game.module.mj.bean.TagGangCardResult;
import game.module.mj.bean.TagWeaveItem;
import game.module.mj.logic.MjDataManager;
import game.module.mj.logic.MjLogic;
import game.session.SessionManager;
import lion.common.MsgCodeAnn;
import lion.netty4.message.MyRequestMessage;
import lion.netty4.message.RequestMessageRaw;
import lion.netty4.message.RequestProtoMessage;
import lua.LuaMessageMj.C2SMJUserDoAction;
import lua.LuaMessageMj.PushMJUserDoAction;

@MsgCodeAnn(msgcode = C2SMJUserDoAction.id, accessLimit = 500)
public class MjOnUserOperateCardProcessor extends PlayingRoleMsgProcessor {

	private static Logger logger = LoggerFactory.getLogger(MjOnUserOperateCardProcessor.class);

	@Override
	public void process(PlayingRole playingRole, RequestMessageRaw request) throws Exception {
		
		int playerId = playingRole.getId();
		logger.info("mj user response action playerId ={}",playerId);
		C2SMJUserDoAction Msg = C2SMJUserDoAction.parse(request);
		final MjRound mjround = MjDataManager.getInstance().getMjRoom(playerId);
		int m_wCurrentUser = mjround.getPlayerIds().indexOf(playerId);
		byte Get_curAction = Msg.action;
		byte card[] = Msg.card;
	
		OnUserOperateCard(m_wCurrentUser,Get_curAction, card,mjround);
	
	}

	@Override
	public void processProto(PlayingRole playingRole, RequestProtoMessage request) throws Exception {
		
	}

	@Override
	public void processWebsocket(PlayingRole playingRole, MyRequestMessage request) throws Exception {

	}

	public boolean OnUserOperateCard(int wChairID, byte cbOperateCode, byte cbOperateCard[], MjRound mjround) {
		// 效验状态
		// assert(m_pITableFrame->GetGameStatus()==GAME_SCENE_PLAY);
		// if (m_pITableFrame->GetGameStatus()!=GAME_SCENE_PLAY)
		// return true;

		// 效验用户
		long starttime = System.currentTimeMillis(); 
		int m_wCurrentUser = mjround.getM_wCurrentUser(); // 获取当前用户
		boolean[] m_bTianDiHu = mjround.getM_bTianDiHu(); // 天地胡
		boolean[] m_bResponse = mjround.getM_bResponse(); // 玩家响应动作
		byte[] m_cbUserAction = mjround.getM_cbUserAction(); // 玩家应该有的动作
		byte[] m_cbPerformAction = mjround.getM_cbPerformAction(); // 执行动作
		byte[][] m_cbOperateCard = mjround.getM_cbOperateCard(); // 会执行动作的扑克
		int m_cbProvideCard = mjround.getM_cbProvideCard(); // 供应的扑克
		byte m_cbOutCardData = mjround.getM_cbOutCardData(); // 打出的扑克
		int m_wResumeUser = mjround.getM_wResumeUser(); // 还原用户
		int m_wProvideUser = mjround.getM_wProvideUser(); // 出该牌的玩家
		byte[] m_cbWeaveItemCount = mjround.getM_cbWeaveItemCount(); // 组合数目
		TagWeaveItem[][] m_WeaveItemArray = mjround.getM_WeaveItemArray(); // 组合扑克（放明牌的数组）
																			// 4
																			// 5扑克最大组合为5
		byte[] m_dwChiHuKind = mjround.getM_dwChiHuKind(); // 吃胡结果
		byte[][] m_cbCardIndex = mjround.getCardIndex(); // 手牌下标
		byte m_cbChiHuCard = mjround.getM_cbChiHuCard(); // 吃胡扑克
		CChiHuRight[] m_ChiHuRight = mjround.getM_ChiHuRight(); // 吃胡权限
		int m_cbOutCardCount = mjround.getM_cbOutCardCount(); // 出牌的数目
		int m_cbSendCardData = mjround.getM_cbSendCardData(); // 派发的扑克
        List<Byte> push_card = mjround.getPushed_card().get(m_wProvideUser); 
		assert ((wChairID == m_wCurrentUser) || (m_wCurrentUser == MjConstants.INVALID_CHAIR));

		if ((wChairID != m_wCurrentUser) && (m_wCurrentUser != MjConstants.INVALID_CHAIR))
			return true;
		
		// 变量设置
		if (cbOperateCode != MjConstants.WIK_CHI_HU)
			m_bTianDiHu[wChairID] = true;
		logger.info("mj user do cards = {},action_code={}", cbOperateCard,cbOperateCode);//
		// 被动动作
		if (m_wCurrentUser == MjConstants.INVALID_CHAIR) {
			// 效验状态
			assert (m_bResponse[wChairID] == false);
			assert (m_cbUserAction[wChairID] != MjConstants.WIK_NULL);
			assert ((cbOperateCode == MjConstants.WIK_NULL) || ((m_cbUserAction[wChairID] & cbOperateCode) != 0));// 玩家可以操作但是没有

			// 效验状态
			if (m_bResponse[wChairID] == true)
				return true;
			if (m_cbUserAction[wChairID] == MjConstants.WIK_NULL)
				return true;
			if ((cbOperateCode != MjConstants.WIK_NULL) && ((m_cbUserAction[wChairID] & cbOperateCode) == 0))
				return true;// 玩家玩家不可以操作

			// 变量定义
			int wTargetUser = wChairID; // 动作执行的用户
			byte cbTargetAction = cbOperateCode; // 执行的动作

			// 设置变量
			m_bResponse[wChairID] = true;
			m_cbPerformAction[wChairID] = cbOperateCode;
			if (cbOperateCard[0] == 0)
				m_cbOperateCard[wChairID][0] = (byte) m_cbProvideCard;
			else
				System.arraycopy(cbOperateCard, 0, m_cbOperateCard[wChairID], 0, cbOperateCard.length);
			int m_wPlayerCount = MjConstants.GAME_PLAYER;
			// 执行判断
			for (int i = 0; i < m_wPlayerCount; i++) {
				// 获取动作
				byte cbUserAction = (m_bResponse[i] == false) ? m_cbUserAction[i] : m_cbPerformAction[i];

				// 优先级别
				byte cbUserActionRank = MjLogic.GetUserActionRank(cbUserAction);
				byte cbTargetActionRank = MjLogic.GetUserActionRank(cbTargetAction);

				// 动作判断
				if (cbUserActionRank > cbTargetActionRank) {
					wTargetUser = i;
					cbTargetAction = cbUserAction;
				}
			}
			if (m_bResponse[wTargetUser] == false)
				return true;

			// 吃胡等待
			if (cbTargetAction == MjConstants.WIK_CHI_HU) {
				for (int i = 0; i < m_wPlayerCount; i++) {
					if ((m_bResponse[i] == false) && ((m_cbUserAction[i] & MjConstants.WIK_CHI_HU) > 0))
						return true;
				}
			}

			// 放弃操作
			if (cbTargetAction == MjConstants.WIK_NULL) {
				// 用户状态
				ZeroMemory(m_bResponse);
				ZeroMemory(m_cbUserAction);
				ZeroMemory(m_cbOperateCard);
				ZeroMemory(m_cbPerformAction);
			//	m_wResumeUser +=1;
             //   if(m_wResumeUser >= 4)
              //  	m_wResumeUser = 0;
                mjround.setM_wCurrentUser(m_wResumeUser);
				// 发送扑克
				MjLogic.DispatchCardData(m_wResumeUser, true, mjround);
				 logger.info("action cost time={}",System.currentTimeMillis()-starttime);
				return true;
			}

			// 变量定义
			byte cbTargetCard = m_cbOperateCard[wTargetUser][0];

			// 出牌变量
			m_cbOutCardData = 0;
			mjround.setM_bSendStatus(true);// m_bSendStatus=true;
			mjround.setM_wOutCardUser(MjConstants.INVALID_CHAIR);// m_wOutCardUser=MjConstants.INVALID_CHAIR;

			// 胡牌操作
			if (cbTargetAction == MjConstants.WIK_CHI_HU) {
				m_cbChiHuCard = cbOperateCard[0];
				if(m_cbChiHuCard==0) {
					m_cbChiHuCard = cbTargetCard;
				}
				// 结束信息
				mjround.setM_cbChiHuCard(cbTargetCard);// m_cbChiHuCard=cbTargetCard;

				for (int i = (m_wProvideUser + m_wPlayerCount + 1)% MjConstants.GAME_PLAYER; i != m_wProvideUser; i = (i + m_wPlayerCount + 1)% MjConstants.GAME_PLAYER) 
				{
					// 过虑判断
					if ((m_cbPerformAction[i] & MjConstants.WIK_CHI_HU) == 0)
						continue;
					// 胡牌判断
					byte cbWeaveItemCount = m_cbWeaveItemCount[i];
					TagWeaveItem[] pWeaveItem = m_WeaveItemArray[i];
					m_dwChiHuKind[i] = MjLogic.AnalyseChiHuCard(m_cbCardIndex[i], pWeaveItem, cbWeaveItemCount,
							cbTargetCard, m_ChiHuRight[i], mjround);
					logger.info("action = {}",m_dwChiHuKind[i]);
					// 插入扑克
					if (m_dwChiHuKind[i] != MjConstants.WIK_NULL) {
						m_cbCardIndex[i][MjLogic.SwitchToCardIndex(m_cbChiHuCard)]++;
						wTargetUser = i;
						 break;
					}
				}
				// 结束游戏
				assert (m_dwChiHuKind[wTargetUser] != MjConstants.WIK_NULL);
				// -------------
				MjLogic.OnEventGameConclude( false, mjround);
				 logger.info("action cost time={}",System.currentTimeMillis()-starttime);
				return true;
			}

			// 组合扑克
			assert (m_cbWeaveItemCount[wTargetUser] < MjConstants.MAX_WEAVE);
			int wIndex = m_cbWeaveItemCount[wTargetUser]++;
			m_WeaveItemArray[wTargetUser][wIndex].cbPublicCard = 1;
			m_WeaveItemArray[wTargetUser][wIndex].cbCenterCard = cbTargetCard;
			m_WeaveItemArray[wTargetUser][wIndex].cbWeaveKind = cbTargetAction;
			m_WeaveItemArray[wTargetUser][wIndex].wProvideUser = (m_wProvideUser == MjConstants.INVALID_CHAIR)
					? wTargetUser : m_wProvideUser;
			m_WeaveItemArray[wTargetUser][wIndex].cbCardData[0] = cbTargetCard;
			if ((cbTargetAction & (MjConstants.WIK_LEFT | MjConstants.WIK_CENTER | MjConstants.WIK_RIGHT)) > 0) {
				m_WeaveItemArray[wTargetUser][wIndex].cbCardData[1] = m_cbOperateCard[wTargetUser][1];
				m_WeaveItemArray[wTargetUser][wIndex].cbCardData[2] = m_cbOperateCard[wTargetUser][2];
			} else {
				m_WeaveItemArray[wTargetUser][wIndex].cbCardData[1] = cbTargetCard;
				m_WeaveItemArray[wTargetUser][wIndex].cbCardData[2] = cbTargetCard;
				if ((cbTargetAction & MjConstants.WIK_GANG) > 0)
					m_WeaveItemArray[wTargetUser][wIndex].cbCardData[3] = cbTargetCard;
			}

			// 删除扑克
			switch (cbTargetAction) {
			case MjConstants.WIK_LEFT: // 上牌操作
			{
				byte[] temp = new byte[2];
				System.arraycopy(m_cbOperateCard[wTargetUser], 1, temp, 0, temp.length);
				// 删除扑克
				if (!MjLogic.RemoveCard(m_cbCardIndex[wTargetUser], temp, (byte) 2)) {
					assert (false);
					return false;
				}

				break;
			}
			case MjConstants.WIK_RIGHT: // 上牌操作
			{
				byte[] temp = new byte[2];
				System.arraycopy(m_cbOperateCard[wTargetUser], 1, temp, 0, temp.length);
				// 删除扑克
				if (!MjLogic.RemoveCard(m_cbCardIndex[wTargetUser], temp, (byte) 2)) {
					assert (false);
					return false;
				}

				break;
			}
			case MjConstants.WIK_CENTER: // 上牌操作
			{
				byte[] temp = new byte[2];
				System.arraycopy(m_cbOperateCard[wTargetUser], 1, temp, 0, temp.length);
				// 删除扑克
				if (!MjLogic.RemoveCard(m_cbCardIndex[wTargetUser], temp, (byte) 2)) {
					assert (false);
					return false;
				}

				break;
			}
			case MjConstants.WIK_PENG: // 碰牌操作
			{
				// 删除扑克
				byte cbRemoveCard[] = { cbTargetCard, cbTargetCard };
				if (!MjLogic.RemoveCard(m_cbCardIndex[wTargetUser], cbRemoveCard, (byte) 2)) {
					assert (false);
					return false;
				}

				break;
			}
			case MjConstants.WIK_GANG: // 杠牌操作
			{
				// 删除扑克,被动动作只存在放杠
				byte cbRemoveCard[] = { cbTargetCard, cbTargetCard, cbTargetCard };
				if (!MjLogic.RemoveCard(m_cbCardIndex[wTargetUser], cbRemoveCard, (byte) cbRemoveCard.length)) {
					assert (false);
					return false;
				}

				break;
			}
			default:
				assert (false);
				return false;
			}
			push_card.remove(push_card.size()-1);//最后一个被碰杠吃后，牌桌上删除该手牌。
			PushMJUserDoAction pushUserAction = new PushMJUserDoAction();
			pushUserAction.action = cbTargetAction;
			pushUserAction.user_index = (byte) wTargetUser;
			logger.info("cbcard={}",cbTargetCard);
		    pushUserAction.ProvideUser = (byte) m_wProvideUser;
			pushUserAction.out_card = new byte[4];
			pushUserAction.out_card[0] = cbTargetCard;
			 if(cbTargetAction>0&((MjConstants.WIK_LEFT|MjConstants.WIK_CENTER|MjConstants.WIK_RIGHT)>0)){
				// CopyMemory( OperateResult.cbOperateCard[1],m_cbOperateCard[wTargetUser][1],2*sizeof(byte));
				 System.arraycopy(m_cbOperateCard[wTargetUser], 1, pushUserAction.out_card, 1, 2);
			 }else if(( cbTargetAction&MjConstants.WIK_PENG)>0 ){
				 pushUserAction.out_card[1] = cbTargetCard;
				 pushUserAction.out_card[2] = cbTargetCard;
			 }
			 if (cbTargetAction==MjConstants.WIK_GANG){
				 pushUserAction.out_card[3] = cbTargetCard;
			 }
			List<Integer> playerIds = mjround.getPlayerIds();
			for (int i = 0; i < playerIds.size(); i++) {
				PlayingRole pr = SessionManager.getInstance().getPlayer(playerIds.get(i));
				if (pr != null && pr.isChannelActive()) {
					pr.writeAndFlush(pushUserAction.build(pr.alloc()));
				}
			}

			// 用户状态
			ZeroMemory(m_bResponse);
			ZeroMemory(m_cbUserAction);
			ZeroMemory(m_cbOperateCard);
			ZeroMemory(m_cbPerformAction);

			// 设置用户
			m_wCurrentUser = wTargetUser;
            mjround.setM_wCurrentUser(m_wCurrentUser);
			// 杠牌处理
			if (cbTargetAction == MjConstants.WIK_GANG) {
				mjround.setM_bGangStatus(true);
				// m_bGangStatus = true;
				mjround.setBuhua_count((byte) (mjround.getBuhua_count()+1));
				MjLogic.DispatchCardData(wTargetUser, true, mjround);
			}
			if (mjround.getM_bEnjoinChiPeng()[m_wCurrentUser] == false) {
				TagGangCardResult GangCardResult = new TagGangCardResult();
				// byte m_cbUserAction1[] = mjround.getM_cbUserAction();
				mjround.getM_wCurrentUser();
				m_cbUserAction[m_wCurrentUser] |= MjLogic.AnalyseGangCard(m_cbCardIndex[m_wCurrentUser],
						m_WeaveItemArray[m_wCurrentUser], m_cbWeaveItemCount[m_wCurrentUser], GangCardResult,
						mjround.getGod_card());
			}
			if (m_cbUserAction[m_wCurrentUser] > 0) // 存在动作
			{
				MjLogic.SendOperateNotify(mjround,(byte)m_cbProvideCard);
			}
			 logger.info("action cost time={}",System.currentTimeMillis()-starttime);
			return true;
		}

		// 主动动作
		if (m_wCurrentUser == wChairID) {
			//设置取消双游状态
//			boolean singlegold[] = mjround.getSingGold();
//			if(cbOperateCode == 0 && singlegold[wChairID]==true)
//				singlegold[wChairID] = false ;//单游后玩家仍然不胡牌清楚胡牌zhuang't
//			// 效验操作
			assert ((cbOperateCode != MjConstants.WIK_NULL) && ((m_cbUserAction[wChairID] & cbOperateCode) != 0));
			if ((cbOperateCode == MjConstants.WIK_NULL) || ((m_cbUserAction[wChairID] & cbOperateCode) == 0))
				return false;

			// 扑克效验
			assert ((cbOperateCode == MjConstants.WIK_NULL) || (cbOperateCode == MjConstants.WIK_CHI_HU)
					|| (MjLogic.IsValidCard(cbOperateCard[0]) == true));
			if ((cbOperateCode != MjConstants.WIK_NULL) && (cbOperateCode != MjConstants.WIK_CHI_HU)
					&& (MjLogic.IsValidCard(cbOperateCard[0]) == false))
				return false;

			// 设置变量
			mjround.setM_bSendStatus(true);// m_bSendStatus=true;
			m_cbUserAction[m_wCurrentUser] = MjConstants.WIK_NULL;
			m_cbPerformAction[m_wCurrentUser] = MjConstants.WIK_NULL;

			boolean bPublic = false;
           
			// 执行动作
			switch (cbOperateCode) {
			case MjConstants.WIK_GANG: // 杠牌操作
			{
				// 变量定义
				byte cbWeaveIndex = (byte) 0xFF;
				byte cbCardIndex = MjLogic.SwitchToCardIndex(cbOperateCard[0]);

				// 杠牌处理
				int a = m_cbCardIndex[wChairID][cbCardIndex];
				if (m_cbCardIndex[wChairID][cbCardIndex] == 1) {
					//明杠处理
					// 寻找组合
					for (byte i = 0; i < m_cbWeaveItemCount[wChairID]; i++) {
						byte cbWeaveKind = m_WeaveItemArray[wChairID][i].cbWeaveKind;
						byte cbCenterCard = m_WeaveItemArray[wChairID][i].cbCenterCard;
						if ((cbCenterCard == cbOperateCard[0]) && (cbWeaveKind == MjConstants.WIK_PENG)) {
							bPublic = true;
							cbWeaveIndex = i;
							break;
						}
					}

					// 效验动作
					assert (cbWeaveIndex != 0xFF);
					if (cbWeaveIndex == 0xFF)
						return false;

					// 组合扑克
					m_WeaveItemArray[wChairID][cbWeaveIndex].cbPublicCard = 1;
					m_WeaveItemArray[wChairID][cbWeaveIndex].cbWeaveKind = cbOperateCode;
					m_WeaveItemArray[wChairID][cbWeaveIndex].cbCenterCard = cbOperateCard[0];
					m_WeaveItemArray[wChairID][cbWeaveIndex].cbCardData[3] = cbOperateCard[0];
				} else {
					// 扑克效验
					assert (m_cbCardIndex[wChairID][cbCardIndex] == 4);
					if (m_cbCardIndex[wChairID][cbCardIndex] != 4)
						return false;

					// 设置变量
					bPublic = false;
					cbWeaveIndex = m_cbWeaveItemCount[wChairID]++;
					m_WeaveItemArray[wChairID][cbWeaveIndex].cbPublicCard = 0;
					m_WeaveItemArray[wChairID][cbWeaveIndex].wProvideUser = wChairID;
					m_WeaveItemArray[wChairID][cbWeaveIndex].cbWeaveKind = cbOperateCode;
					m_WeaveItemArray[wChairID][cbWeaveIndex].cbCenterCard = cbOperateCard[0];
					for (byte j = 0; j < 4; j++)
						m_WeaveItemArray[wChairID][cbWeaveIndex].cbCardData[j] = cbOperateCard[0];
				}

				// 删除扑克
				m_cbCardIndex[wChairID][cbCardIndex] = 0;

				mjround.setM_bGangStatus(true);// m_bGangStatus = true;

				PushMJUserDoAction pushUserAction = new PushMJUserDoAction();
				pushUserAction.action = cbOperateCode;
				pushUserAction.out_card = new byte[4];
				pushUserAction.out_card=cbOperateCard;
				pushUserAction.user_index = (byte) wChairID;
				pushUserAction.ProvideUser = (byte)-1;
				List<Integer> playerIds = mjround.getPlayerIds();
				for (int i = 0; i < playerIds.size(); i++) {
					PlayingRole pr = SessionManager.getInstance().getPlayer(playerIds.get(i));
					if (pr != null && pr.isChannelActive()) {
						pr.writeAndFlush(pushUserAction.build(pr.alloc()));
					}
				}
				// 效验动作
				boolean bAroseAction = false;
				if (bPublic == true)
					bAroseAction = MjLogic.EstimateUserRespond(wChairID, cbOperateCard[0],
							MjConstants.EstimatKind_GangCard, mjround);

				// 发送扑克
				if (bAroseAction == false) {
					mjround.setBuhua_count((byte) (mjround.getBuhua_count()+1));
					MjLogic.DispatchCardData(wChairID, true, mjround);
				}
				 logger.info("action cost time={}",System.currentTimeMillis()-starttime);
				return true;
			}
			case MjConstants.WIK_CHI_HU: // 吃胡操作
			{
				// 吃牌权位
				if (m_cbOutCardCount == 0) {
					m_wProvideUser = m_wCurrentUser;
					m_cbProvideCard = m_cbSendCardData;
				}

				// 普通胡牌
				byte cbWeaveItemCount = m_cbWeaveItemCount[wChairID];
				TagWeaveItem[] pWeaveItem = m_WeaveItemArray[wChairID];
				// --------------------
				if (!MjLogic.RemoveCard(m_cbCardIndex[wChairID], (byte) m_cbProvideCard)) {
					assert (false);
					return false;
				}
				m_dwChiHuKind[wChairID] = MjLogic.AnalyseChiHuCard(m_cbCardIndex[wChairID], pWeaveItem,
						cbWeaveItemCount, (byte) m_cbProvideCard, m_ChiHuRight[wChairID], mjround);
				m_cbCardIndex[wChairID][MjLogic.SwitchToCardIndex((byte) m_cbProvideCard)]++;

				// 结束信息
				m_cbChiHuCard = (byte) m_cbProvideCard;
                mjround.setM_cbChiHuCard(m_cbChiHuCard);
				// 结束游戏
				MjLogic.OnEventGameConclude(false,mjround);
			    logger.info("action cost time={}",System.currentTimeMillis()-starttime);
				return true;
			}
			}
			 logger.info("action cost time={}",System.currentTimeMillis()-starttime);
			return true;
		}
		return false;
	}

	public void ZeroMemory(byte[] array) {
		for (int i = 0; i < array.length; i++) {
			array[i] = 0;
		}
	}

	public void ZeroMemory(boolean[] array) {
		for (int i = 0; i < array.length; i++) {
			array[i] = false;
		}
	}

	public void ZeroMemory(byte[][] array) {
		for (int i = 0; i < array.length; i++) {
			for (int j = 0; j < array[i].length; j++) {
				array[i][j] = 0;
			}
		}
	}

}
